package com.wlyy.his.controller.registration;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wlyy.his.bean.register.dto.RegistrationCoverDataDto;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.wlyy.his.bean.register.qo.GuhaoReserveCancelQo;
import com.wlyy.his.bean.register.qo.GuhaoReserveQo;
import com.wlyy.his.common.api.CommonResult;
import com.wlyy.his.common.enums.DeleteFlagEnum;
import com.wlyy.his.common.enums.GuaHaoStateEnum;
import com.wlyy.his.common.exception.ApiException;
import com.wlyy.his.entity.registration.HisDoctorSchedule;
import com.wlyy.his.entity.registration.HisRegisterRecord;
import com.wlyy.his.common.enums.GuahaoTypeEnum;
import com.wlyy.his.service.registration.IHisDoctorScheduleService;
import com.wlyy.his.service.ums.IHisRegisterRecordService;
import com.wlyy.his.ze.bean.base.BASEINFO;

import com.wlyy.his.ze.api.ZeGuoNeiApiService;
import com.wlyy.his.ze.bean.base.FEIYONGXX;
import com.wlyy.his.ze.bean.request.GUAHAOXXCX_IN_request;
import com.wlyy.his.ze.bean.request.GUAHAOYYTH_IN_request;
import com.wlyy.his.ze.bean.request.GUAHAOYY_IN_request;
import com.wlyy.his.ze.bean.response.GUAHAOXXCX_OUT;
import com.wlyy.his.ze.bean.response.GUAHAOYYTH_OUT;
import com.wlyy.his.ze.bean.response.GUAHAOYY_OUT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * @author: 10097
 * @date: 2021/9/2 09:39
 * @description: 预约挂号服务
 */
@Slf4j
@RestController
@RequestMapping("registration")
public class HisRegistrationController {

    @Resource
    private IHisRegisterRecordService hisRegisterRecordService;

    @Resource
    private IHisDoctorScheduleService hisDoctorScheduleService;


    /**
     * 预约挂号（非当日的）
     * 尽量不要在同一个接口实现当日和预约两种挂号，避免逻辑混乱
     *
     * @param reserveQo 参数
     */
    @PostMapping("reserve")
    public CommonResult<String> reserve(@RequestBody @Validated GuhaoReserveQo reserveQo) {
        //其实这里还可以在预约挂号时发现 已有同科室的预约记录时  将记录同步过来，这属于业务问题了，但这样实现的话，更合理点的需要，将排班中的医生，科室，排班信息 3个区分开，在同步数据的
        //的时候对数据进行拆分，目前排班表中包含医生的介绍信息等大量的文本字段，日后查询效率必定会有影响，目前时间比较紧张不进行拆分
        //查询本地排班信息 用于数据保存
        HisDoctorSchedule doctorSchedule = hisDoctorScheduleService.getOne(Wrappers.lambdaQuery(HisDoctorSchedule.class).eq(HisDoctorSchedule::getIdSchedule, reserveQo.getIdSchedule()));
        if (null == doctorSchedule) {
            throw new ApiException("挂号失败:排班记录不存在");
        }
        //校验当天是否成功预约同科室的号 仅本地校验  减少请求医院的api 这个校验级别是患者，即通过患者的病案号，可能会出现一个病案号被多个账号绑定的情况出现重复的挂号
        //严格的来说这个校验并不能抗住并发请求
        List<HisRegisterRecord> records = hisRegisterRecordService.list(Wrappers.lambdaQuery(HisRegisterRecord.class)
                .eq(HisRegisterRecord::getDeleteFlag, DeleteFlagEnum.NORMAL.getFlag())
                .eq(HisRegisterRecord::getCardNo, reserveQo.getCaseNo())
                .eq(HisRegisterRecord::getDeptCode, doctorSchedule.getDeptCode())
                .eq(HisRegisterRecord::getPreState, GuaHaoStateEnum.SUCCESS.getState())
                .eq(HisRegisterRecord::getScheduleTime, doctorSchedule.getScheduleTime())
        );
        if (CollUtil.isNotEmpty(records)) {
            throw new ApiException("挂号失败:同一个科室不允许重复挂号");
        }
        //拼接浙二 api接口参数
        GUAHAOYY_IN_request request = JSON.parseObject(JSON.toJSONStringWithDateFormat(reserveQo, "yyyy-MM-dd"), GUAHAOYY_IN_request.class);
        request.setKESHIDM(doctorSchedule.getDeptCode());
        request.setRIQI(LocalDateTimeUtil.format(doctorSchedule.getScheduleTime(), "yyyy-MM-dd"));
        request.setYIZHOUPBID(doctorSchedule.getIdWeekSchedule());
        request.setYISHENGDM(doctorSchedule.getDoctorCode());

        BASEINFO baseinfo = new BASEINFO();
        //这个参数其实不重要，任何一个院区都可以进行预约
        baseinfo.setFENYUANDM(reserveQo.getHisCode());
        request.setBASEINFO(baseinfo);
        GUAHAOYY_OUT guahaoyyOut;
        try {
            guahaoyyOut = ZeGuoNeiApiService.guahaoReserve00536(request);
            //返回结果小于0 则是异常
            if (Integer.parseInt(guahaoyyOut.getOUTMSG().getERRNO()) < 0) {
                //打印异常信息
                log.error("浙二预约挂号接口调用失败,请求参数:{},返回:{}", JSON.toJSONString(reserveQo), JSON.toJSONString(guahaoyyOut));
                throw new ApiException("预约失败:" + guahaoyyOut.getOUTMSG().getERRMSG());
            }
        } catch (Exception e) {
            //直接打印异常信息 这么处理不好但是前期排查问题方便
            e.printStackTrace();
            //返回异常提示
            throw new ApiException("预约失败");
        }
        //保存预约记录 这里保存我也很纠结，原则上来说必须要数据落盘。但是这个保存的动作数据处理太多，很难保证不会在保存前出问题，现阶段，先这么做
        // 对其中使用到计算的字段捕获异常但是不抛出 先保证数据落盘，目前来说主要是第三方的返回结果不完全可信，因此这部分必须捕获异常
        RegistrationCoverDataDto registerRecordData = BeanUtil.toBean(doctorSchedule, RegistrationCoverDataDto.class);
        //入参拷贝
        BeanUtil.copyProperties(reserveQo, registerRecordData);
        registerRecordData.setHisCode(reserveQo.getHisCode());
        registerRecordData.setRecordType(GuahaoTypeEnum.YUYUE.getCode());

        //可考虑做一个拼音转换工具
        registerRecordData.setNamePy("");
        registerRecordData.setTakePassword(guahaoyyOut.getQUHAOMM());
        //需要从结果guahaoyyOut中计算
        try {
            if (!guahaoyyOut.getFEIYONGXX().isEmpty()) {
                BigDecimal price = BigDecimal.ZERO;
                for (FEIYONGXX feiyongxx : guahaoyyOut.getFEIYONGXX()) {
                    price = new BigDecimal(feiyongxx.getDANJIA()).add(price);
                }
                registerRecordData.setFeeTotal(price.toString());
            }
        } catch (Exception e) {
            log.info("预约挂号结果计算费用总金额失败:{}", JSON.toJSONString(guahaoyyOut));
            e.printStackTrace();
        }
        registerRecordData.setPreState(GuaHaoStateEnum.SUCCESS.getState());
        HisRegisterRecord registerRecord = BeanUtil.toBean(registerRecordData, HisRegisterRecord.class);
        // TODO: 2021/9/2 补全预约人
        registerRecord.setCreateUser("123");
        registerRecord.setCreateTime(LocalDateTime.now());
        hisRegisterRecordService.save(registerRecord);

        //保持返回风格一致
        return CommonResult.success("");
    }


    /**
     * 挂号
     */
    public void guahao() {
        // TODO: 2021/9/3 挂号 暂未实现
    }

    /**
     * 取消预约
     * 不需要区分院区
     * 取消后，在号源解锁的一段时间内不能重复挂号，预计时间大概5分钟左右
     * @param cancleQo 入参
     */
    @PostMapping("reserve/cancel")
    public CommonResult<String> cancelReserve(@RequestBody @Validated GuhaoReserveCancelQo cancleQo) {
        HisRegisterRecord registerRecord = hisRegisterRecordService.getById(cancleQo.getIdArRecord());
        if (null == registerRecord) {
            throw new ApiException("预约记录不存在");
        }
        //取消后可以给患者添加一个锁，挂号平台取消后一段时间是不能再次进行预约的这个规则需要在了解一下
        GUAHAOYYTH_IN_request request = JSON.parseObject(JSON.toJSONString(cancleQo), GUAHAOYYTH_IN_request.class);
        BASEINFO baseinfo = new BASEINFO();
        baseinfo.setFENYUANDM(cancleQo.getHisCode());
        request.setBASEINFO(baseinfo);
        GUAHAOYYTH_OUT guahaoyythOut = ZeGuoNeiApiService.guahaoCancel00539(request);
        //对返回结果进行判断
        if (Integer.parseInt(guahaoyythOut.getOUTMSG().getERRNO()) < 0) {
            //暂时直接返回医院的提示
            throw new ApiException("取消挂号失败:" + guahaoyythOut.getOUTMSG().getERRMSG());
        }
        //不全量更新
        HisRegisterRecord updateBean = new HisRegisterRecord();
        updateBean.setUpdateTime(LocalDateTime.now());
        // TODO: 2021/9/2 更新人信息
        updateBean.setUpdateUser("123");
        updateBean.setIdArRecord(cancleQo.getIdArRecord());
        updateBean.setPreState(GuaHaoStateEnum.CANCEL.getState());
        hisRegisterRecordService.updateById(updateBean);

        //保持返回风格一致
        return CommonResult.success("");
    }

    /**
     * 挂号信息查询
     * 需要区分院区查询
     */
    @PostMapping("reserve/cx")
    public void testReserveDetail() {
        GUAHAOXXCX_IN_request request = new GUAHAOXXCX_IN_request();
        BASEINFO baseinfo = new BASEINFO();
        baseinfo.setFENYUANDM("0");
        request.setBASEINFO(baseinfo);
        request.setRIQI("");
        request.setGUAHAOBC("");
        request.setKESHIDM("");
        request.setJIUZHENKH("");
        request.setJIUZHENKLX("");
        request.setZHENGJIANLX("");
        request.setZHENGJIANHM("340323199403017131");
        request.setXINGMING("张家乐");
        request.setYISHENGDM("");
        request.setGUAHAOID("");
        request.setCHAXUNFS("");

        GUAHAOXXCX_OUT guahaoxxcx_out = ZeGuoNeiApiService.guahaoInfoSearch00537(request);
        System.out.println(JSON.toJSONString(guahaoxxcx_out));
    }

}
